﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using TDT.Land.Entity;
using TDT.Land.BusinessLogic.Base;
using TDT.Land.Models;
using TDT.Helper.Security;
using TDT.Helper.Data;
using TDT.Land.Utilities;

namespace TDT.Land.BusinessLogic
{
    /// <summary>
    /// Viết business logic ở đây
    /// - Viết các methods lấy phân quyền 
    /// </summary>
    public class SecurityRepo : BaseRepo
    {
        #region Properties
        private static SecurityRepo _instanceSecurity = null;
        public static SecurityRepo Instance
        {
            get
            {
                if (_instanceSecurity == null)
                {
                    _instanceSecurity = new SecurityRepo();
                }
                return _instanceSecurity;
            }
        }

        static Dictionary<Guid, List<DataPermission>> userPermissions;

        /// <summary>Cache tất cả những thông tin phân quyền liên quan đến một user.</summary>
        public static Dictionary<Guid, List<DataPermission>> UserPermissions
        {
            get
            {
                if (userPermissions == null)
                {
                    userPermissions = new Dictionary<Guid, List<DataPermission>>();
                }

                return userPermissions;
            }
        }

        #endregion

        #region Permission

        /// <summary>
        /// Tải tất cả thông tin phân quyền của một người dùng.
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        public List<DataPermission> LoadPermission(Guid userID)
        {          
            //Nguồn gốc của phân quyền: Kiểm tra user thuộc những nhóm người dùng trung tâm, chi nhánh và nhóm dữ liệu nào?
            var listDataPermission = EntityService.Sys_DataPermission.Where(d => d.Sys_Group != null && d.Sys_Group.IsActivate.HasValue && d.Sys_Group.IsActivate.Value
                    && d.UserID == userID).Select(d => new DataPermission
                    {
                        UserID = d.UserID,
                        GroupID = d.GroupID,
                        DataGroups = d.DataGroups
                    }).ToList();

            //Lấy tất cả danh sách nhóm người dùng mà user này trực thuộc (được phân quyền)
            List<Guid?> listGroupID = listDataPermission.Select(d => d.GroupID).Distinct().ToList();

            var listGroupPermission = EntityService.Sys_GroupPermission.Where(d => listGroupID.Contains(d.GroupID))
                .Select(d => new GroupPermission
                {
                    GroupID = d.GroupID,
                    PrivilegeNumber = d.PrivilegeNumber,
                    ResourceName = d.Sys_Resource.ResourceName
                }).ToList();

            foreach (var dataPermission in listDataPermission)
            {         
                dataPermission.ListGroupPermission = listGroupPermission.Where(d =>
                    d.GroupID == dataPermission.GroupID).ToList();
            }

            if (UserPermissions.ContainsKey(userID))
            {
                UserPermissions[userID] = listDataPermission;
            }
            else
            {
                //Lưu thông tin phân quyền của người dùng này
                UserPermissions.Add(userID, listDataPermission);
            }

            return listDataPermission;
        }

        /// <summary>
        /// Kiểm tra người dùng có quyền thao tác trên một permission hay không?
        /// </summary>
        /// <param name="userID">User cần kiểm tra</param>
        /// <param name="privilegeType">Loại thao tác</param>
        /// <param name="permission">Tên quyền cần kiểm tra</param>
        /// <returns></returns>
        public bool CheckPermission(Guid userID, PrivilegeType privilegeType, string permission)
        {
            bool result = false;

            if (userID != Guid.Empty )
            {
                if (UserPermissions != null && !UserPermissions.Any() && userID != Guid.Empty)
                {
                    LoadPermission(userID);
                }

                if (UserPermissions != null && UserPermissions.ContainsKey(userID))
                {
                    result = UserPermissions[userID].Any(d => d.ListGroupPermission != null && d.ListGroupPermission.Any(p =>
                        p.ResourceName == permission && SecurityHelper.CheckPrivilege(privilegeType, p.PrivilegeNumber.GetInteger())));
                }
            }
            else
            {
                result = true;
            }

            return result;
        }
        
        #endregion
    }
    
    #region class object permission

    public class GroupPermission
    {
        public Guid ID { get; set; }
        public Guid? GroupID { get; set; }
        public Guid? ResourceID { get; set; }
        public string ModuleName { get; set; }
        public string ResourceType { get; set; }
        public string ResourceName { get; set; }
        public int? PrivilegeNumber { get; set; }

      
        public partial class FieldNames
        {
            public const string All = "All";
            public const string View = "View";
            public const string Delete = "Delete";
            public const string Edit = "Edit";
            public const string Create = "Create";
            public const string Name = "Name";
        }
    }

    public class DataPermission
    {
        public Guid ID { get; set; }
        public Guid? UserID { get; set; }
        public Guid? GroupID { get; set; }
        public string GroupName { get; set; }

        public List<int> OfficeNumbers { get; set; }
        public List<Guid> ListOfficeID { get; set; }
        public string OfficeNames { get; set; }

        public byte[] DataGroups { get; set; }
        public List<int> DataGroupNumbers { get; set; }
        public List<Guid> ListDataGroupID { get; set; }
        public string DataGroupNames { get; set; }

        /// <summary>Lưu thông tin group permission của user</summary>
        public List<GroupPermission> ListGroupPermission
        {
            get;
            set;
        }
    }


    #endregion

}
